<?php
/**
 * Created by PhpStorm.
 * User: Hanson
 * Date: 2016/8/29
 * Time: 19:43
 */

namespace App\Service;

use App\Exceptions\UserNotFoundException;
use App\Jobs\SaveBindUser;
use App\Model\User;
use App\Repository\UserRepository;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Symfony\Component\DomCrawler\Crawler;
use WechatService as Wechat;
use Log;

class BindService{

    const INDEX_URL = 'http://ngrok.zark.in:20073/';

    const LOGIN_URL = 'http://ngrok.zark.in:20073/default2.aspx';

    const CODE_URL = 'http://ngrok.zark.in:20073/CheckCode.aspx';

    const INFO_URL = 'http://gcu.info.gike.pw/pub/jiaowuchu/myInfo?yhbh=';

    /**
     * @var Client
     */
    public $client;

    /**
     * @var UserRepository
     */
    public $user;

    /**
     * @var Request
     */
    public $request;

    public function __construct(UserRepository $user)
    {
        $this->user = $user;
        $this->client = new Client();
    }

    public function bind($request)
    {
        $this->request = $request;

        if(($msg = $this->checkUser()) !== true){
            return $msg;
        }

        try{

            return $this->login();

        }catch(\Exception $e){

            Log::error($e->getMessage());
            Wechat::report('教务连接', $e);

            return redirect('user/bind');
        }
    }

    private function checkUser()
    {
        $user = $this->user->getUserByNumber($this->request->get('txtUserName'));

        if($user && $user->name){
            return '该学号已绑定其他微信号，请先解除绑定';
        }

        return true;
    }

    /**
     * @return bool|string
     */
    private function login()
    {
        try{
            $response = $this->client->post(self::LOGIN_URL, [
                'form_params' => $this->request->all(),
                'headers' => [
                    'Content-Type' => 'application/x-www-form-urlencoded',
                    'Accept' => 'text/html, application/xhtml+xml, */*',
                    'Cookie' => $this->getCookie(),
                ]
            ]);
        }catch(\Exception $e){
            Wechat::report('教务处登录', $e);
            return false;
        }

       $content = iconv('gb2312', 'utf-8//IGNORE', $response->getBody()->getContents());

        if(str_contains($content, '验证码不正确')){
            return '验证码不正确！';
        }

        if(str_contains($content, '密码错误')){
            return '密码错误！';
        }

        if(str_contains($content, '欢迎您：')){

            $openId = \Auth::guard('wechat')->user()->open_id;

            $array = [
                'openId' => $openId,
                'number' => $this->request->get('txtUserName'),
                'sessionId' => $this->request->get('sessionId'),
                'cookieId' => $this->request->get('cookieId'),
                'password' => $this->request->get('TextBox2'),
                'role' => $this->request->get('RadioButtonList1') == '%BD%CC%CA%A6' ? 1 : 0,
            ];

            dispatch(new SaveBindUser($array));

            $user = $this->user->firstOrCreate(['open_id' => $openId]);

            return $user->update(['number' => $array['number'], 'password' => $array['password']]) ? true : false;

        }else{
            Log::error($content);
            return '未知错误！请检查是否能登录教务系统';
        }
    }

    private function getResponse()
    {
        $response = $this->client->post(self::INDEX_URL);
        return $response;
    }

    public function prepare()
    {
        $response = $this->getResponse();

        $sessionId = $this->getSessionId($response->getHeader('Set-Cookie'));

        $cookieId = $this->getCookieId($response->getHeader('Set-Cookie'));

        $viewState = $this->getViewState($response->getBody()->getContents());

        return ['sessionId' => $sessionId, 'viewState' => $viewState, 'cookieId' => $cookieId];
    }

    public function getCookie($session = null, $cookie = null)
    {
        if($this->request) {

            $session = $session ?: $this->request->get('sessionId');

            $cookie = $cookie ?: $this->request->get('cookieId');
        }

        $cookie = $cookie ? ';array_cookie=' . $cookie : '';

        return  'ASP.NET_SessionId=' . $session . $cookie;
    }

    /**
     * @param $cookie
     * @return mixed
     */
    public function getSessionId($cookie)
    {
        return explode('=', explode(';', $cookie[0])[0])[1];
    }

    /**
     * @param $cookie
     * @return mixed
     */
    public function getCookieId($cookie)
    {
        return isset($cookie[1]) ? explode('=', explode(';', $cookie[1])[0])[1] : null;
    }


    private function getViewState($body)
    {
        $crawler = new Crawler($body);

        return $crawler->filter('form input[name="__VIEWSTATE"]')->attr('value');
    }

    public function getCode($session, $cookie = null)
    {
        $cookie = $cookie ? '; array_cookie=' . $cookie : '';

        $response = $this->client->get(self::CODE_URL, [
            'headers' => [
                'Cookie' => 'ASP.NET_SessionId=' . $session . $cookie
            ]
        ]);

        return $response->getBody()->getContents();
    }

    /**
     * 根据学号获取登录表单信息
     *
     * @param $number
     * @return array
     * @throws UserNotFoundException
     */
    public function getFormByNumber($number)
    {
        $user = $this->user->getUserByNumber($number);

        if(!$user){
            throw new UserNotFoundException($number);
        }

        $prepare = $this->prepare();

        return [
            'RadioButtonList1' => '%D1%A7%C9%FA',
            'Button1' => '',
            'lbLanguage' => '',
            'hidPdrs' => '',
            'hidsc' => '',
            'cookieId' => $prepare['cookieId'],
            'sessionId' => $prepare['sessionId'],
            '__VIEWSTATE' => $prepare['viewState'],
            'txtUserName' => $user->number,
            'TextBox2' => $user->password,
        ];

    }

    public function getInfo($number)
    {
        try {
            $response = $this->client->get(static::INFO_URL . $number);
        }catch(\Exception $e){
            return [];
        }

        $content = $response->getBody()->getContents();

        $crawler = new Crawler($content);

        $name = $crawler->filter('#mytable tr td')->eq(1)->filter('span')->eq(0)->text();

        $collegeInfo = $crawler->filter('table')->eq(1)->filter('tr');

        $college = $collegeInfo->eq(0)->filter('td')->eq(1)->text();

        $major = $collegeInfo->eq(1)->filter('td')->eq(1)->text();

        $table = $crawler->filter('table')->eq(2)->filter('tr');

        $gender = $table->eq(0)->filter('td')->eq(1)->text();

        $grade = $table->eq(3)->filter('td')->eq(1)->text();

        $class = $table->eq(4)->filter('td')->eq(1)->text();

        return compact('name', 'college', 'major', 'gender', 'grade', 'class');
    }

    /**
     * 根据学号获取信息
     *
     * @param $number
     * @return array|bool|mixed
     */
    public function getUserInfo($number)
    {
        $user = $this->user->getUserWithClass($number);

        if($user){
            $user = $user->toArray();
            $user['class'] = $user['class']['name'];
        }else{
            $user = $this->getInfo($number);

            if(!$user){
                return false;
            }
        }

        return $user;
    }
}